🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / testing / src / commonMain / kotlin / org / meshtastic / core / testing / FakeRadioInterfaceService.kt
Displaying Raw • Download
core/testing/src/commonMain/kotlin/org/meshtastic/core/testing/FakeRadioInterfaceService.kt 7730823aad5ffe461199820be209e18d09b0ee07 (7730823a) Text, 10.77 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.testing
Tff7b72import T7ee787kotlinx.atomicfu.atomic
Tff7b72import T7ee787kotlinx.atomicfu.locks.SynchronizedObject
Tff7b72import T7ee787kotlinx.atomicfu.locks.synchronized
Tff7b72import T7ee787kotlinx.coroutines.CompletableDeferred
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.MainScope
Tff7b72import T7ee787kotlinx.coroutines.NonCancellable
Tff7b72import T7ee787kotlinx.coroutines.channels.Channel
Tff7b72import T7ee787kotlinx.coroutines.flow.Flow
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableSharedFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.receiveAsFlow
Tff7b72import T7ee787kotlinx.coroutines.sync.Mutex
Tff7b72import T7ee787kotlinx.coroutines.sync.withLock
Tff7b72import T7ee787kotlinx.coroutines.withContext
Tff7b72import T7ee787okio.ByteString.Companion.toByteString
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.DeviceType
Tff7b72import T7ee787org.meshtastic.core.model.InterfaceId
Tff7b72import T7ee787org.meshtastic.core.model.MeshActivity
Tff7b72import T7ee787org.meshtastic.core.repository.RadioInterfaceService
Tff7b72import T7ee787org.meshtastic.core.repository.RadioSessionContext
Tff7b72import T7ee787org.meshtastic.core.repository.RadioSessionLease
Tff7b72import T7ee787org.meshtastic.core.repository.ReceivedRadioFrame
Tff7b72import T7ee787org.meshtastic.core.repository.TransportDisconnectReason
T8b949e/**
* A test double for [RadioInterfaceService] that provides an in-memory implementation.
*
* The [connectionState] here mirrors the transport-level semantics of the real implementation. In production, only
* [MeshConnectionManager][org.meshtastic.core.repository.MeshConnectionManager] observes this flow; tests should verify
* that bridging behavior rather than consuming it directly from UI/feature test code (use
* [FakeServiceRepository.connectionState] instead). Address selection remains separate from transport admission:
* [connect] and an in-flight [restartTransport] publish a fresh monotonically increasing session generation.
*/
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tff7b72class T56d364FakeRadioInterfaceServiceTb4b4b4(Tff7b72override Tff7b72val Te6edf3serviceScopeTb4b4b4: Te6edf3CoroutineScope Tff7b72= Te6edf3MainScopeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4: Te6edf3RadioInterfaceService Tb4b4b4{
Tff7b72override Tff7b72val Te6edf3supportedDeviceTypesTb4b4b4: Te6edf3ListTff7b72<Te6edf3DeviceTypeTff7b72> Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)
T8b949e/** Transport-level connection state (raw hardware link status). */
Tff7b72private Tff7b72val Te6edf3_connectionState Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3ConnectionStateTff7b72>Tb4b4b4(Te6edf3ConnectionStateTb4b4b4.Te6edf3DisconnectedTb4b4b4)
Tff7b72override Tff7b72val Te6edf3connectionStateTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ConnectionStateTff7b72> Tff7b72= Te6edf3_connectionState
Tff7b72private Tff7b72val Te6edf3_currentDeviceAddressFlow Tff7b72= Te6edf3MutableStateFlowTff7b72<Tffa657String?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72override Tff7b72val Te6edf3currentDeviceAddressFlowTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72> Tff7b72= Te6edf3_currentDeviceAddressFlow
Tff7b72private Tff7b72val Te6edf3_sessionGeneration Tff7b72= Te6edf3MutableStateFlowTb4b4b4(T79c0ff0LTb4b4b4)
Tff7b72override Tff7b72val Te6edf3sessionGenerationTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657LongTff7b72> Tff7b72= Te6edf3_sessionGeneration
Tff7b72private Tff7b72val Te6edf3_activeSession Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3RadioSessionContext?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72override Tff7b72val Te6edf3activeSessionTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3RadioSessionContext?Tff7b72> Tff7b72= Te6edf3_activeSession
Tff7b72private Tff7b72val Te6edf3sessionAdmissionLock Tff7b72= Te6edf3SynchronizedObjectTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3sessionAdmissionOpen Tff7b72= Tff7b72false
Tff7b72private Tff7b72var Te6edf3admittedSessionOperations Tff7b72= T79c0ff0
Tff7b72private Tff7b72var Te6edf3sessionDrainWaiterTb4b4b4: Te6edf3CompletableDeferredTff7b72<Tffa657UnitTff7b72>Tff7b72? Tff7b72= Tff7b72null
Tff7b72private Tff7b72val Te6edf3sessionOperationMutex Tff7b72= Te6edf3MutexTb4b4b4(Tb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffisSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{ Te6edf3sessionAdmissionOpen Tff7b72&Tff7b72& Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Te6edf3session Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrunIfSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4, Te6edf3blockTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sessionAdmissionOpen Tff7b72|Tff7b72| Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72!Tff7b72= Te6edf3sessionTb4b4b4) Tff7b72returnTf0883e@synchronized Tff7b72false
Te6edf3blockTb4b4b4(Tb4b4b4)
Tff7b72true
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffrunWithSessionLeaseTb4b4b4(
Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4,
Te6edf3blockTb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3RadioSessionLeaseTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3admittedSession Tff7b72=
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3active Tff7b72= Te6edf3_activeSessionTb4b4b4.Te6edf3value
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sessionAdmissionOpen Tff7b72|Tff7b72| Te6edf3active Tff7b72!Tff7b72= Te6edf3sessionTb4b4b4) Tb4b4b4{
Tff7b72null
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3admittedSessionOperationsTff7b72+Tff7b72+
Te6edf3active
Tb4b4b4}
Tb4b4b4} Tff7b72?: Tff7b72return Tff7b72false
Tff7b72val Te6edf3lease Tff7b72=
Tff7b72object Tb4b4b4: T56d364RadioSessionLease Tb4b4b4{
Tff7b72override Tff7b72val Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContext Tff7b72= Te6edf3session
Tff7b72override Tff7b72fun Td2a8ffisCurrentTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{ Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Te6edf3admittedSession Tb4b4b4}
Tb4b4b4}
Tff7b72try Tb4b4b4{
Te6edf3blockTb4b4b4(Te6edf3leaseTb4b4b4)
Tff7b72return Tff7b72true
Tb4b4b4} Tff7b72finally Tb4b4b4{
Tff7b72val Te6edf3waiter Tff7b72=
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{
Te6edf3checkTb4b4b4(Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Te6edf3admittedSessionTb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffFake session changed before an admitted operation released its leaseTa5d6ff"
Tb4b4b4}
Te6edf3checkTb4b4b4(Te6edf3admittedSessionOperations Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffSession operation count underflowTa5d6ff" Tb4b4b4}
Te6edf3admittedSessionOperationsTff7b72-Tff7b72-
Tff7b72if Tb4b4b4(Te6edf3admittedSessionOperations Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3sessionDrainWaiterTb4b4b4.Te6edf3also Tb4b4b4{ Te6edf3sessionDrainWaiter Tff7b72= Tff7b72null Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72null
Tb4b4b4}
Tb4b4b4}
Te6edf3waiterTff7b72?.Te6edf3completeTb4b4b4(Tffa657UnitTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffrunWhileSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4, Te6edf3blockTb4b4b4: Te6edf3suspend Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3sessionOperationMutexTb4b4b4.Te6edf3withLock Tb4b4b4{ Te6edf3runWithSessionLeaseTb4b4b4(Te6edf3sessionTb4b4b4) Tb4b4b4{ Te6edf3blockTb4b4b4(Tb4b4b4) Tb4b4b4} Tb4b4b4}
T8b949e// Use an unbounded Channel to mirror SharedRadioInterfaceService semantics. A MutableSharedFlow would
T8b949e// hide the stop/start backlog bug that motivated the resetReceivedBuffer() API.
Tff7b72private Tff7b72val Te6edf3_receivedData Tff7b72= Te6edf3ChannelTff7b72<Te6edf3ReceivedRadioFrameTff7b72>Tb4b4b4(Te6edf3ChannelTb4b4b4.Te6edf3UNLIMITEDTb4b4b4)
Tff7b72override Tff7b72val Te6edf3receivedDataTb4b4b4: Te6edf3FlowTff7b72<Te6edf3ReceivedRadioFrameTff7b72> Tff7b72= Te6edf3_receivedDataTb4b4b4.Te6edf3receiveAsFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_meshActivity Tff7b72= Te6edf3MutableSharedFlowTff7b72<Te6edf3MeshActivityTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72override Tff7b72val Te6edf3meshActivityTb4b4b4: Te6edf3FlowTff7b72<Te6edf3MeshActivityTff7b72> Tff7b72= Te6edf3_meshActivityTb4b4b4.Te6edf3asFlowTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_connectionError Tff7b72= Te6edf3MutableSharedFlowTff7b72<Tffa657StringTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72override Tff7b72val Te6edf3connectionErrorTb4b4b4: Te6edf3FlowTff7b72<Tffa657StringTff7b72> Tff7b72= Te6edf3_connectionErrorTb4b4b4.Te6edf3asFlowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3sentToRadio Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3ByteArrayTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72var Te6edf3connectCalled Tff7b72= Tff7b72false
Tff7b72var Te6edf3restartTransportCalledTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72false
Te6edf3private Tff7b72set
Tff7b72override Tff7b72fun Td2a8ffisMockTransportTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72= Tff7b72true
Tff7b72override Tff7b72fun Td2a8ffsendToRadioTb4b4b4(Te6edf3bytesTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tb4b4b4{
Te6edf3sentToRadioTb4b4b4.Te6edf3addTb4b4b4(Te6edf3bytesTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffconnectTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3connectCalled Tff7b72= Tff7b72true
Tff7b72if Tb4b4b4(Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Te6edf3admitSelectedSessionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffdisconnectTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3connectCalled Tff7b72= Tff7b72false
Te6edf3revokeActiveSessionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffrestartTransportTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3restartTransportCalled Tff7b72= Tff7b72true
Tff7b72if Tb4b4b4(Te6edf3connectCalled Tff7b72&Tff7b72& Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3revokeActiveSessionTb4b4b4(Tb4b4b4)
Te6edf3admitSelectedSessionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetDeviceAddressTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String? Tff7b72= Te6edf3_currentDeviceAddressFlowTb4b4b4.Te6edf3value
Tff7b72override Tff7b72fun Td2a8ffsetDeviceAddressTb4b4b4(Te6edf3deviceAddrTb4b4b4: Tffa657String?Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Te6edf3_currentDeviceAddressFlowTb4b4b4.Te6edf3value Tff7b72= Te6edf3deviceAddr
Tff7b72return Tff7b72true
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffadmitSelectedSessionTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3address Tff7b72= Te6edf3_currentDeviceAddressFlowTb4b4b4.Te6edf3value
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{
Te6edf3checkTb4b4b4(Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3admittedSessionOperations Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffCannot admit a fake transport while the previous session is still drainingTa5d6ff"
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3address Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3sessionAdmissionOpen Tff7b72= Tff7b72false
Tff7b72return
Tb4b4b4}
Tff7b72val Te6edf3generation Tff7b72= Te6edf3_sessionGenerationTb4b4b4.Te6edf3value Tff7b72+ T79c0ff1
Te6edf3_sessionGenerationTb4b4b4.Te6edf3value Tff7b72= Te6edf3generation
Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72= Te6edf3RadioSessionContextTb4b4b4(Te6edf3generationTb4b4b4, Te6edf3addressTb4b4b4)
Te6edf3sessionAdmissionOpen Tff7b72= Tff7b72true
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffrevokeActiveSessionTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3session Tff7b72= Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{ Te6edf3_activeSessionTb4b4b4.Te6edf3value Tb4b4b4} Tff7b72?: Tff7b72return
Te6edf3withContextTb4b4b4(Te6edf3NonCancellableTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3waiter Tff7b72=
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72!Tff7b72= Te6edf3sessionTb4b4b4) Tff7b72returnTf0883e@synchronized Tff7b72null
Te6edf3sessionAdmissionOpen Tff7b72= Tff7b72false
Tff7b72if Tb4b4b4(Te6edf3admittedSessionOperations Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72null
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3sessionDrainWaiter Tff7b72?: Te6edf3CompletableDeferredTff7b72<Tffa657UnitTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3also Tb4b4b4{ Te6edf3sessionDrainWaiter Tff7b72= Tffa657it Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3waiterTff7b72?.Te6edf3awaitTb4b4b4(Tb4b4b4)
Te6edf3synchronizedTb4b4b4(Te6edf3sessionAdmissionLockTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Te6edf3sessionTb4b4b4) Tb4b4b4{
Te6edf3checkTb4b4b4(Te6edf3admittedSessionOperations Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFake session revoked before admitted operations drainedTa5d6ff" Tb4b4b4}
Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72= Tff7b72null
Te6edf3sessionDrainWaiter Tff7b72= Tff7b72null
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8fftoInterfaceAddressTb4b4b4(Te6edf3interfaceIdTb4b4b4: Te6edf3InterfaceIdTb4b4b4, Te6edf3restTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Tffd700$Te6edf3interfaceIdTa5d6ff:Tffd700$Te6edf3restTa5d6ff"
Tff7b72override Tff7b72fun Td2a8ffonConnectTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_connectionStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3Connected
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonDisconnectTb4b4b4(Te6edf3isPermanentTb4b4b4: Tffa657BooleanTb4b4b4, Te6edf3errorMessageTb4b4b4: Tffa657String?Tb4b4b4, Te6edf3reasonTb4b4b4: Te6edf3TransportDisconnectReason?Tb4b4b4) Tb4b4b4{
Te6edf3_connectionStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3Disconnected
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffhandleFromRadioTb4b4b4(Te6edf3bytesTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3session Tff7b72= Te6edf3_activeSessionTb4b4b4.Te6edf3value Tff7b72?: Tff7b72return
Te6edf3runIfSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4) Tb4b4b4{ Te6edf3emitFromRadioTb4b4b4(Te6edf3bytesTb4b4b4, Te6edf3sessionTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffresetReceivedBufferTb4b4b4(Tb4b4b4) Tb4b4b4{
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffEmptyWhileBlockTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffControlFlowWithEmptyBodyTa5d6ff"Tb4b4b4)
Tff7b72while Tb4b4b4(Te6edf3_receivedDataTb4b4b4.Te6edf3tryReceiveTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3isSuccessTb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
T8b949e// --- Helper methods for testing ---
Tff7b72fun Td2a8ffemitFromRadioTb4b4b4(Te6edf3bytesTb4b4b4: Te6edf3ByteArrayTb4b4b4, Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4) Tb4b4b4{
Te6edf3_receivedDataTb4b4b4.Te6edf3trySendTb4b4b4(Te6edf3ReceivedRadioFrameTb4b4b4(Te6edf3bytesTb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3sessionTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffsetConnectionStateTb4b4b4(Te6edf3stateTb4b4b4: Te6edf3ConnectionStateTb4b4b4) Tb4b4b4{
Te6edf3_connectionStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3state
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3gattCacheInvalidationRequested Tff7b72= Te6edf3atomicTb4b4b4(Tff7b72falseTb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffrequestGattCacheInvalidationOnNextConnectTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3gattCacheInvalidationRequestedTb4b4b4.Te6edf3value Tff7b72= Tff7b72true
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffconsumeGattCacheInvalidationRequestTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72= Te6edf3gattCacheInvalidationRequestedTb4b4b4.Te6edf3getAndSetTb4b4b4(Tff7b72falseTb4b4b4)
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.07s